package useraddress

import (
	"context"
	// "fmt"
	"strings"

	"mall/common/modelx"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetUserAddressListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewGetUserAddressListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserAddressListLogic {
	return &GetUserAddressListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *GetUserAddressListLogic) GetUserAddressList(in *user.BaseListReq) (*user.UserAddressListResp, error) {
	// logrus.Info(fmt.Sprintf("GetUserAddressList BaseListReq: %+v", in))
	// Limit:10  Preload:"userAddress:Id,Consignee,Mobile,Province,City,District,DetailedAddress,PostalCode,IsDefault"  EagerLoad:"userAddress:total"  Filter:"Status,equalTo:1;UserId,equalTo:10021"  VisitorId:10021  PlatformId:1

	if in.Filter == nil || len(*in.Filter) == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	preloadMap, eagerLoadMap := modelx.ParsePreloadAndEagerLoad(in.Preload, in.EagerLoad)
	// logrus.Info(fmt.Sprintf("GetUserAddressList preloadMap: %+v", preloadMap))
	// userAddress:[Id Consignee Mobile Province City District DetailedAddress PostalCode IsDefault]]
	// logrus.Info(fmt.Sprintf("GetUserAddressList eagerLoadMap: %+v", eagerLoadMap))
	// map[userAddress:[total]]

	userAddressEntityName := model.RpcEntityNames.UserAddress
	if _, ok := model.RpcEntityPreloadMap[userAddressEntityName]; !ok {
		return &user.UserAddressListResp{}, nil
	}

	userAddressRepositoryName := model.RepositoryNames.UserAddress
	columnMap, ok := model.RepositoryPreloadMap[userAddressRepositoryName]
	if !ok {
		return &user.UserAddressListResp{}, nil
	}

	var selectCols []string
	if preloadFields, ok := preloadMap[userAddressEntityName]; ok {
		selectCols = modelx.ParseSelectColumns(preloadFields, columnMap)
	}

	filterMap := modelx.ParseFilter(in.Filter, columnMap)
	// logrus.Info(fmt.Sprintf("GetUserAddressList filterMap: %+v", filterMap))
	// map[status:map[equalTo:[1]] user_id:map[equalTo:[10021]]]
	if filterMap == nil {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	orderBy := modelx.ParseSorter(in.Sorter, columnMap)
	// logrus.Info(fmt.Sprintf("GetUserAddressList orderBy: %s", orderBy))
	//
	if len(orderBy) == 0 {
		orderBy = model.UserAddressColumns.IsDefault + " DESC, " + model.UserAddressColumns.LastUsedAt + " DESC, " + model.UserAddressColumns.UserAddressID + " DESC"
	}

	res, count, err := l.svcCtx.UserAddress.GetList(l.ctx, model.M{
		"offset":  in.Offset,
		"limit":   in.Limit,
		"orderBy": orderBy,
		"select":  strings.Join(selectCols, ","),
	}, 2, filterMap)
	if err != nil {
		return nil, err
	}

	hasNextPage, hasPreviousPage := modelx.ParseCount(count)
	resp := &user.UserAddressListResp{
		HasNextPage:     pointy.GetPointer(hasNextPage),
		HasPreviousPage: pointy.GetPointer(hasPreviousPage),
	}

	var total int64
	if len(res) > 0 {
		if eagerLoadEntities, ok := eagerLoadMap[userAddressEntityName]; ok {
			for _, entity := range eagerLoadEntities {
				if entity == "total" {
					_, total, err = l.svcCtx.UserAddress.GetList(l.ctx, model.M{}, 0, filterMap)
					if err != nil {
						total = 0
					}
				}
			}
		}

		for _, v := range res {
			var isDefault uint32
			if v.IsDefault > 0 {
				isDefault = 1
			}
			var geographic []*user.UserMetaInfo
			if v.Geographic.Valid {
				if err = v.Geographic.Unmarshal(&geographic); err != nil {
					logx.Errorw("GetUserAddressList Geographic.Unmarshal err", logx.Field("detail", err.Error()))
				}
			}

			resp.List = append(resp.List, &user.UserAddressInfo{
				Id:              &v.UserAddressID,
				UserId:          &v.UserID,
				Label:           &v.Label,
				Consignee:       &v.Consignee,
				Mobile:          &v.Mobile,
				Province:        &v.Province,
				City:            &v.City,
				District:        &v.District,
				Street:          &v.Street,
				DetailedAddress: &v.DetailedAddress,
				PostalCode:      &v.PostalCode,
				RegionCode:      &v.RegionCode,
				IsDefault:       pointy.GetPointer(isDefault),
				Status:          pointy.GetPointer(uint32(v.Status)),
				LastUsedAt:      pointy.GetPointer(modelx.FormatNullDotTime(v.LastUsedAt, "")),
				CreatedAt:       pointy.GetPointer(modelx.FormatTime(v.CreatedAt, "")),
				UpdatedAt:       pointy.GetPointer(modelx.FormatTime(v.UpdatedAt, "")),
				Geographic:      geographic,
			})
		}
	}
	resp.Total = uint64(total)

	return resp, nil
}
